# -*- coding: utf-8 -*-
# @Time    : 2020/3/14 下午1:07
# @Author  : lilong


"""
简单工厂类

（1）客户类和工厂类分开。
（2）消费者任何时候需要某种产品，只需向工厂请求即可。消费者无须修改就可以接纳新产品。
（3）缺点是当产品修改时，工厂类也要做相应的修改。如：如何创建及如何向客户端提供。

产品类的定义和工厂类定义没有关系，产品类可以采用继承的方法；
工厂类是写产品逻辑的地方，返回产品对象；

缺点：
随着产品线的增加，会有越来越多的产品，这时简单工厂模式就不行了。因为工厂需要添加新的产品逻辑，工厂就要停工，
其他的产品也不能再生产，影响很大。所以就有了: 简单工厂 ——> 工厂方法。

缺点：工厂类集成了所有产品的创建逻辑，当工厂类出现问题，所有产品都会出现问题；还有当新增加产品都会修改工厂类，违背开闭原则。

"""

# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
from abc import ABCMeta, abstractmethod


class Coffee(metaclass=ABCMeta):
    """产品抽象类"""

    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name

    @abstractmethod
    def getTaste(self):
        pass


class LatteCaffe(Coffee):
    """产品类：拿铁咖啡
    """

    def __init__(self, name):
        super().__init__(name)

    def getTaste(self):
        return "轻柔而香醇"


class MochaCoffee(Coffee):
    """产品类：摩卡咖啡
    """

    def __init__(self, name):
        super().__init__(name)

    def getTaste(self):
        return "丝滑与醇厚"


class Coffeemaker:
    """工厂类：这里生产产品对象，主要是产品生产的逻辑
    当产品修改时，工厂类也要做相应的修改
    """

    @staticmethod
    def makeCoffee(coffeeBean):
        """通过staticmethod装饰器修饰来定义一个静态方法"""
        if coffeeBean == "拿铁咖啡豆":
            coffee = LatteCaffe("拿铁咖啡")
        elif coffeeBean == "摩卡咖啡豆":
            coffee = MochaCoffee("摩卡咖啡")
        else:
            raise ValueError("不支持的参数：%s" % coffeeBean)
        return coffee


def testCoffeeMaker():
    # 消费者无需做任何的修改，就可以得到新产品
    latte = Coffeemaker.makeCoffee("拿铁咖啡豆")
    print("%s已为您准备好了，口感：%s。请慢慢享用！" % (latte.getName(), latte.getTaste()))
    mocha = Coffeemaker.makeCoffee("摩卡咖啡豆")
    print("%s已为您准备好了，口感：%s。请慢慢享用！" % (mocha.getName(), mocha.getTaste()))


testCoffeeMaker()
